﻿using PwdMgr.CommonContract;
using PwdMgr.PwdMgrService.UserAuthentication;
using PwdMgr.Utility.Exceptions;
using PwdMgrUI.Objects;
using PwdMgrUI.Utils;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace PwdMgrUI.ViewModels
{
    internal class RegisterViewModel : ViewModelBase
    {
        private IAuth _auth;

        public RegisterViewModel()
        {
            _auth = AuthFactory.CreateInstance();

            _questions = new ObservableCollection<string>
            {
                "Where were you born?",
                "Who is your fist lover?"
            };

            _question = _questions[0];
        }

        private string _username;
        public string Username
        {
            get { return _username; }
            set
            {
                _username = value;
                OnPropertyChanged("Username");
            }
        }

        private Func<string> _getPassword = Delegates.GetPasswordNotImplemented;
        public Func<string> GetPassword
        {
            get { return _getPassword; }
            set { _getPassword = value; }
        }
        private Action<string> _setPassword = Delegates.SetPasswordNotImplemented;
        public Action<string> SetPassword
        {
            get { return _setPassword; }
            set { _setPassword = value; }
        }

        public string Password
        {
            get { return GetPassword(); }
            set
            {
                SetPassword(value);
                OnPropertyChanged("Password");
            }
        }

        private Func<string> _getConfirmPassword = Delegates.GetPasswordNotImplemented;
        public Func<string> GetConfirmPassword
        {
            get { return _getConfirmPassword; }
            set { _getConfirmPassword = value; }
        }
        private Action<string> _setConfirmPassword = Delegates.SetPasswordNotImplemented;
        public Action<string> SetConfirmPassword
        {
            get { return _setConfirmPassword; }
            set { _setConfirmPassword = value; }
        }
        public string ConfirmPassword
        {
            get { return GetConfirmPassword(); }
            set
            {
                SetConfirmPassword(value);
                OnPropertyChanged("ConfirmPassword");
            }
        }

        private ObservableCollection<string> _questions;
        public ObservableCollection<string> Questions
        {
            get { return _questions; }
            set 
            { 
                _questions = value;
                OnPropertyChanged("Questions");
            }
        }

        private string _email;
        public string Email
        {
            get { return _email; }
            set 
            { 
                _email = value;
                OnPropertyChanged("Email");
            }
        }

        private string _question;
        public string Question
        {
            get { return _question; }
            set 
            { 
                _question = value;
                OnPropertyChanged("Question");
            }
        }

        private string _answer;
        public string Answer
        {
            get { return _answer; }
            set 
            { 
                _answer = value;
                OnPropertyChanged("Answer");
            }
        }

        public const string OKCommandID = "OK";
        [Command("OKExecute")]
        public ICommand OKCommand
        {
            get;
            protected set;
        }

        private void OKExecute(object parameter)
        {
            IDictionary<CommandError, string> errors =
                new Dictionary<CommandError, string>();
            if (!CheckValidation(errors))
            {
                OnCommandFinished(OKCommandID, CommandResult.Failed, errors);
                return;
            }

            UserInfo userInfo = new UserInfo
            {
                Username = Username,
                Password = Password,
                Email = Email,
                Question = Question,
                Answer = Answer,
            };

            try
            {
                _auth.CreateUser(userInfo);
            }
            catch (UserAlreadyExistException)
            {
                errors.Add(CommandError.UserAlreadyExist, "UserAlreadyExist".I18N());
                OnCommandFinished(OKCommandID, CommandResult.Failed, errors);
                return;
            }
            catch (Exception e)
            {
                errors.Add(CommandError.UserAlreadyExist, e.ToString());
                OnCommandFinished(OKCommandID, CommandResult.Failed, errors);
                return;
            }

            OnCommandFinished(OKCommandID, CommandResult.Success, null);
        }

        private bool CheckValidation(IDictionary<CommandError, string> errors)
        {
            bool validate = true;
            if (string.IsNullOrWhiteSpace(Username))
            {
                errors.Add(CommandError.InvalidateUsername, "InvalidateUsername".I18N());
                validate = false;
            }

            if (string.IsNullOrEmpty(Password))
            {
                errors.Add(CommandError.InvalidatePassword, "Invalidate Password.");
                validate = false;
            }

            if (!string.Equals(Password, ConfirmPassword, StringComparison.Ordinal))
            {
                errors.Add(CommandError.PasswordAndConfirmPasswordNotEquals,
                    "Password and Confirm Password should be the same.");
                validate = false;
            }

            return validate;
        }
    }
}
